loadfile("lib/status.lua")()
loadfile("lib/state_machine.lua")()
loadfile("lib/turtle_utils.lua")()

function d()
	return statusGetProgData()
end

function selectSlot(n)
	while true do
		for i=2	,16 do
			turtle.select(i)
			if turtle.compareTo(n) and turtle.getItemCount(i) > 1 then
				return
			end
		end
		os.sleep(0.5)
	end
end

progStates = {
	init=function()
		d().z = 1
		statusSave()
		return 'placeMiddle'
	end,
	placeMiddle=function()
		digDown()
			selectSlot(2)
		turtle.placeDown()
		return 'lookLeft'
	end,
	lookLeft=function()
		turtle.turnLeft()
		d().facing = 1
		return 'goLeft1'
	end,
	goLeft1=function()
		if not forward(1) then
			return 'end'
		end
		return 'placeFloorLeft1'
	end,
	placeFloorLeft1=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goLeft2'
	end,
	goLeft2=function()
		if not forward(1) then
			return 'end'
		end
		return 'placeFloorLeft2'
	end,
	placeFloorLeft2=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goLeft3'
	end,
	goLeft3=function()
		if not forward(1) then
			return 'end'
		end
		return 'placeFloorLeft3'
	end,
	placeFloorLeft3=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goUpLeft'
	end,
	goUpLeft=function()
		if not up(1) then
			return 'end'
		end
		return 'placeFenceLeft'
	end,
	placeFenceLeft=function()
		selectSlot(3)
		turtle.placeDown()
		if d().dir == 2 then
			return 'goUpLeft2'
		else
			return 'turnBackLeft1'
		end
	end,
	goUpLeft2=function()
		if not up(1) then
			return 'end'
		end
		return 'placeFenceLeft2'
	end,
	placeFenceLeft2=function()
		selectSlot(3)
		turtle.placeDown()
		return 'turnBackLeftA3'
	end,
	turnBackLeftA3=function()
		turtle.turnRight()
		d().facing = 0
		return 'turnBackLeftA4'
	end,
	turnBackLeftA4=function()
		turtle.turnRight()
		d().facing = 2
		return 'goRightA1'
	end,
	turnBackLeft1=function()
		turtle.turnRight()
		d().facing = 0
		return 'turnBackLeft2'
	end,
	turnBackLeft2=function()
		turtle.turnRight()
		d().facing = 2
		return 'goRight1'
	end,


	goRightA1=function()
		if not forward(1) then
			return 'end'
		end
		if (d().z % 5) == 0 then
			return 'placeLeftTorchTurnA1'
		end
		return 'goDownA1'
	end,
	placeLeftTorchTurnA1=function()
		turtle.turnLeft()
		return 'placeLeftTorchTurnA2'
	end,
	placeLeftTorchTurnA2=function()
		turtle.turnLeft()
		return 'placeLeftTorchA1'
	end,
	placeLeftTorchA1=function()
		selectSlot(5)
		turtle.place()
		return 'placeLeftTorchTurnA3'
	end,
	placeLeftTorchTurnA3=function()
		turtle.turnRight()
		return 'placeLeftTorchTurnA4'
	end,
	placeLeftTorchTurnA4=function()
		turtle.turnRight()
		return 'goDownA1'
	end,
	goDownA1=function()
		if not down(1) then
			return 'end'
		end
		return 'goRight2'
	end,


	goRight1=function()
		if not forward(1) then
			return 'end'
		end
		if (d().z % 5) == 0 then
			return 'placeLeftTorchTurn1'
		end
		return 'goRight2'
	end,
	placeLeftTorchTurn1=function()
		turtle.turnLeft()
		return 'placeLeftTorchTurn2'
	end,
	placeLeftTorchTurn2=function()
		turtle.turnLeft()
		return 'placeLeftTorch1'
	end,
	placeLeftTorch1=function()
		selectSlot(5)
		turtle.place()
		return 'placeLeftTorchTurn3'
	end,
	placeLeftTorchTurn3=function()
		turtle.turnRight()
		return 'placeLeftTorchTurn4'
	end,
	placeLeftTorchTurn4=function()
		turtle.turnRight()
		return 'goRight2'
	end,
	goRight2=function()
		if not forward(1) then
			return 'end'
		end
		return 'placeTrack1'
	end,
	placeTrack1=function()
		selectSlot(4)
		turtle.placeDown()
		return 'goRight3'
	end,
	goRight3=function()
		if not forward(1) then
			return 'end'
		end
		return 'goRight4'
	end,
	goRight4=function()
		if not forward(1) then
			return 'end'
		end
		return 'goDownRight1'
	end,
	goDownRight1=function()
		if not down(1) then
			return 'end'
		end
		return 'placeFloorRight1'
	end,
	placeFloorRight1=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goUpRight1'
	end,
	goUpRight1=function()
		if not up(1) then
			return 'end'
		end
		return 'placeTrack2'
	end,
	placeTrack2=function()
		selectSlot(4)
		turtle.placeDown()
		return 'goRight5'
	end,
	goRight5=function()
		if not forward(1) then
			return 'end'
		end
		return 'goDownRight2'
	end,
	goDownRight2=function()
		if not down(1) then
			return 'end'
		end
		return 'placeFloorRight2'
	end,
	placeFloorRight2=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goRight6'
	end,
	goRight6=function()
		if not forward(1) then
			return 'end'
		end
		return 'placeFloorRight3'
	end,
	placeFloorRight3=function()
		digDown()
		selectSlot(2)
		turtle.placeDown()
		return 'goUpRight'
	end,
	goUpRight=function()
		if not up(1) then
			return 'end'
		end
		return 'placeFenceRight'
	end,
	placeFenceRight=function()
		selectSlot(3)
		turtle.placeDown()
		return 'turnBackRight1'
	end,
	goUpRight2=function()
		if not up(1) then
			return 'end'
		end
		if d().dir == 2 then
			return 'placeFenceRight2'
		else
			if (d().z % 5) == 0 then
				return 'placeRightTorch1'
			else
				return 'goLeft5'
			end
		end
	end,
	
	
	placeFenceRight2=function()
		selectSlot(3)
		turtle.placeDown()
		return 'goLeftA1'
	end,
	goLeftA1=function()
		if not forward(1) then
			return 'end'
		end
		if (d().z % 5) == 0 then
			return 'placeRightTorchTurnA1'
		else
			return 'goLeft6'
		end
	end,
	placeRightTorchTurnA1=function()
		turtle.turnLeft()
		return 'placeRightTorchTurnA2'
	end,
	placeRightTorchTurnA2=function()
		turtle.turnLeft()
		return 'placeRightTorchA1'
	end,
	placeRightTorchA1=function()
		selectSlot(5)
		turtle.place()
		return 'placeRightTorchTurnA3'
	end,
	placeRightTorchTurnA3=function()
		turtle.turnRight()
		return 'placeRightTorchTurnA4'
	end,
	placeRightTorchTurnA4=function()
		turtle.turnRight()
		return 'goLeft6'
	end,
	
	
	turnBackRight1=function()
		turtle.turnLeft()
		d().facing = 0
		return 'turnBackRight2'
	end,
	turnBackRight2=function()
		turtle.turnLeft()
		d().facing = 1
		return 'goUpRight2'
	end,
	placeRightTorch1=function()
		selectSlot(5)
		turtle.placeDown()
		return 'goLeft5'
	end,
	goLeft5=function()
		if not forward(1) then
			return 'end'
		end
		return 'goLeft6'
	end,
	goLeft6=function()
		if not forward(1) then
			return 'end'
		end
		return 'goLeft7'
	end,
	goLeft7=function()
		if not forward(1) then
			return 'end'
		end
		return 'goLeft8'
	end,
	goLeft8=function()
		if not forward(1) then
			return 'end'
		end
		return 'goLeft9'
	end,
	goLeft9=function()
		if not forward(1) then
			return 'end'
		end
		if d().dir == 2 then
			return 'turnBackLeft3'
		else
			return 'goLeft10'
		end
	end,
	goLeft10=function()
		if not forward(1) then
			return 'end'
		end
		return 'turnBackLeft3'
	end,
	turnBackLeft3=function()
		turtle.turnRight()
		d().facing = 0
		return 'turnBackLeft4'
	end,
	turnBackLeft4=function()
		turtle.turnRight()
		d().facing = 2
		return 'goRight7'
	end,
	goRight7=function()
		if not forward(1) then
			return 'end'
		end
		return 'goRight8'
	end,
	goRight8=function()
		if not forward(1) then
			return 'end'
		end
		if d().dir == 2 then
			return 'turnForward'
		end
		return 'goRight9'
	end,
	goRight9=function()
		if not forward(1) then
			return 'end'
		end
		return 'turnForward'
	end,
	turnForward=function()
		turtle.turnLeft()
		return 'goForward'
	end,
	goForward=function()
		if d().z > d().len then
			return 'end'
		end
		if not forward(1) then
			return 'end'
		end
		d().z = d().z + 1
		return 'goDown'
	end,
	goDown=function()
		if not down(1) then
			return 'end'
		end
		if d().dir == 1 then
			return 'placeMiddle'
		else
			return 'goDown2'
		end
	end,
	goDown2=function()
		if not down(1) then
			return 'end'
		end
		if d().dir == 0 then
			return 'placeMiddle'
		else
			return 'goDown3'
		end
	end,
	goDown3=function()
		if not down(1) then
			return 'end'
		end
		return 'placeMiddle'
	end
}

arg = { ... }

if (arg[1] == nil) then
	if not statusLoad() then
		print("Usage: build_railway LENGTH")
	end
	smStart(progStates)
else
	len = tonumber(arg[1])
	local dir = 0;
	if arg[2] ~= nil then
		if arg[2] == 'up' then
			dir = 1;
		elseif arg[2] == 'down' then
			dir = 2;
		else
			print("Invalid 2nd argument must be 'up' or 'down'")
			exit()
		end
	end
	
	if not statusLoad() then
		statusInit('build_railway')
		d().len = len
		d().dir = dir
	end

	smStart(progStates)
end